﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;

namespace Asol.Reporting.Support.Components
{
    /// <summary>
    /// Panel pro snadné vybírání souboru/adresáře (GetFile, PutFile, GetDirectory)
    /// </summary>
	public class FileSelectPanel : DPanel
	{
		#region Vnitřní konstrukce
        /// <summary>
        /// Konstruktor
        /// </summary>
		public FileSelectPanel()
		{
			this.InitializeComponents();
		}
		private TextBox Txt;
		private Button Btn;
		private void InitializeComponents()
		{
			this.Txt = new TextBox();
			this.Txt.Location = new Point(0, 0);
			this.Txt.Size = new Size(256, 22);
			this.Txt.Font = new Font(this.Font.FontFamily, 9F, FontStyle.Regular);
			this.Txt.GotFocus += new EventHandler(Txt_GotFocus);
			this.Txt.LostFocus += new EventHandler(Txt_LostFocus);

			this.Btn = new Button();
			this.Btn.Location = new Point(256, 0);
			this.Btn.Size = new Size(24, 21);
			this.Btn.Text = "...";
			this.Btn.Click += new EventHandler(Btn_Click);

			this.BorderStyle = System.Windows.Forms.BorderStyle.None;
			this.Controls.Add(this.Txt);
			this.Controls.Add(this.Btn);
			this.Size = new Size(280, 22);
			this.MinimumSize = new Size(75, 22);
			this.MaximumSize = new Size(3600, 22);

			this.Txt.Anchor = (AnchorStyles)(AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top);
			this.Btn.Anchor = (AnchorStyles)(AnchorStyles.Right | AnchorStyles.Top);

		}

		void Txt_GotFocus(object sender, EventArgs e)
		{
			this._TextOld = this.Txt.Text;
		}

		void Txt_LostFocus(object sender, EventArgs e)
		{
			if (!String.Equals(this.Txt.Text, this._TextOld))
				this._SelectedPath = this.Txt.Text;
		}
		private string _TextOld;

		void Btn_Click(object sender, EventArgs e)
		{
            this._OpenDialog();
        }
		#endregion
        #region Property a eventy
        /// <summary>
        /// Defaultní cesta, která se nabízí v situaci, kdy není zadán soubor
        /// </summary>
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		[Browsable(false)]
        public string DefaultPath { get; set; }
        /// <summary>
        /// Aktuálně zadaná cesta
        /// </summary>
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		[Browsable(false)]
		public string SelectedPath
		{
			get { return this._SelectedPath; }
			set { this._SetSelectedPath(value); }
		}
        /// <summary>
        /// Aktuální režim výběru cesty
        /// </summary>
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		[Browsable(false)]
		public PathSelectMode SelectMode
		{
			get { return this._SelectMode; }
			set { this._SelectMode = value; }
		}
		/// <summary>
		/// Gets or sets the current file name filter string, which determines the choices
		/// that appear in the "Save as file type" or "Files of type" box in the dialog box.
		/// </summary>
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
		[Category("Appearance")]
		[DefaultValue("")]
		[Description("Gets or sets the current file name filter string, which determines the choices that appear in the \"Save as file type\" or \"Files of type\" box in the dialog box.")]
		public string Filter { get; set; }
		/// <summary>
		/// Gets or sets the index of the filter currently selected in the file dialog box.
		/// Returns: A value containing the index of the filter currently selected in the file dialog box. The default value is 1.
		/// </summary>
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
		[Category("Appearance")]
		[Description("Gets or sets the index of the filter currently selected in the file dialog box. Returns: A value containing the index of the filter currently selected in the file dialog box. The default value is 1.")]
		[DefaultValue(1)]
		public int FilterIndex { get; set; }
		/// <summary>
		/// Nápovědný titulek v dialogovém okně
		/// </summary>
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
		[Category("Appearance")]
		[Description("Nápovědný titulek v dialogovém okně")]
		public string Title { get; set; }
		/// <summary>
		/// Event volaný po změně hodnoty SelectedPath.
		/// </summary>
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
		[Category("Action")]
		[Description("Event volaný po změně hodnoty SelectedPath.")]
		public event EventHandler SelectedPathChanged;
        #endregion
        #region Výkonné metody
        private void _OpenDialog()
        {
            switch (this.SelectMode)
            {
                case PathSelectMode.PutFile:
                    using (SaveFileDialog sfd = new SaveFileDialog())
                    {
                        sfd.AutoUpgradeEnabled = true;
                        sfd.CreatePrompt = false;
                        sfd.Filter = this.Filter;
                        sfd.FilterIndex = this.FilterIndex;
                        sfd.CheckFileExists = false;
                        sfd.CheckPathExists = true;
                        sfd.RestoreDirectory = true;
                        sfd.SupportMultiDottedExtensions = true;
                        sfd.Title = this.Title;
                        sfd.InitialDirectory = this._GetInitialPath();
                        sfd.FileName = this._GetInitialFile();

                        DialogResult result = sfd.ShowDialog();
                        if (result == DialogResult.OK && sfd.FileName != null)
                            this._SetSelectedPath(sfd.FileName);
                    }
                    break;
                case PathSelectMode.GetDirectory:
                    using (FolderBrowserDialog fbd = new FolderBrowserDialog())
                    {
                        fbd.Description = this.Title;
                        fbd.SelectedPath = this._GetInitialPath();
                        fbd.ShowNewFolderButton = true;

                        DialogResult result = fbd.ShowDialog();
                        if (result == DialogResult.OK && fbd.SelectedPath != null)
                            this._SetSelectedPath(fbd.SelectedPath);
                    }
                    break;
                case PathSelectMode.GetDirectoryFromFile:
                    using (OpenFileDialog ofd = new OpenFileDialog())
                    {
                        ofd.AutoUpgradeEnabled = true;
                        ofd.Filter = this.Filter;
                        ofd.FilterIndex = this.FilterIndex;
                        ofd.CheckFileExists = true;
                        ofd.CheckPathExists = true;
                        ofd.Multiselect = false;
                        ofd.RestoreDirectory = true;
                        ofd.SupportMultiDottedExtensions = true;
                        ofd.Title = this.Title;
                        ofd.InitialDirectory = this._GetInitialPath();
                        ofd.FileName = this._GetInitialFile();

                        DialogResult result = ofd.ShowDialog();
                        if (result == DialogResult.OK && ofd.FileName != null)
                            this._SetSelectedPath(ofd.FileName);
                    }
                    break;
                default:
                    using (OpenFileDialog ofd = new OpenFileDialog())
                    {
                        ofd.AutoUpgradeEnabled = true;
                        ofd.Filter = this.Filter;
                        ofd.FilterIndex = this.FilterIndex;
                        ofd.CheckFileExists = true;
                        ofd.CheckPathExists = true;
                        ofd.Multiselect = false;
                        ofd.RestoreDirectory = true;
                        ofd.SupportMultiDottedExtensions = true;
                        ofd.Title = this.Title;
                        ofd.InitialDirectory = this._GetInitialPath();
                        ofd.FileName = this._GetInitialFile();

                        DialogResult result = ofd.ShowDialog();
                        if (result == DialogResult.OK && ofd.FileName != null)
                            this._SetSelectedPath(ofd.FileName);
                    }
                    break;
            }
        }
        /// <summary>
        /// Vrací výchozí adresář pro otevírání dialogu. Buď z vybraného souboru, nebo this.DefaultPath, nebo "".
        /// </summary>
        /// <returns></returns>
        private string _GetInitialPath()
        {
            string initialPath = this._SelectedPath;
            if (!String.IsNullOrEmpty(initialPath))
            {
                if (this.SelectMode == PathSelectMode.GetDirectory || this.SelectMode == PathSelectMode.GetDirectoryFromFile)
                    return initialPath;
                return System.IO.Path.GetDirectoryName(initialPath);
            }
            if (!String.IsNullOrEmpty(this.DefaultPath))
                return this.DefaultPath;
            return "";
        }
        /// <summary>
        /// Vrací výchozí soubor pro otevírání dialogu. Buď z vybraného souboru, nebo "".
        /// </summary>
        /// <returns></returns>
        private string _GetInitialFile()
        {
            if (this.SelectMode == PathSelectMode.GetDirectory || this.SelectMode == PathSelectMode.GetDirectoryFromFile) return "";

            string initialPath = this._SelectedPath;
            if (!String.IsNullOrEmpty(initialPath))
                return System.IO.Path.GetFileName(initialPath);
            return "";
        }
		private void OnSelectedPathChanged()
		{
			if (this.SelectedPathChanged != null)
				this.SelectedPathChanged(this, EventArgs.Empty);
		}
		/// <summary>
		/// Privátní property, setování detekuje změnu a při změně volá event SelectedPathChanged.
		/// </summary>
        private string _SelectedPath
		{
			get { return __SelectedPath;}
			set
			{
				bool isChange = !String.Equals(value, __SelectedPath);
				__SelectedPath = value;
				if (isChange)
					OnSelectedPathChanged();
			}
		}
		private string __SelectedPath;
		private PathSelectMode _SelectMode;
		private void _SetSelectedPath(string path)
		{
            string p = path;
            if (this.SelectMode == PathSelectMode.GetDirectoryFromFile && !String.IsNullOrEmpty(path))
            {
                p = path.Trim();
                if (p[p.Length - 1] != System.IO.Path.DirectorySeparatorChar)
                    p = System.IO.Path.GetDirectoryName(p) + System.IO.Path.DirectorySeparatorChar;
            }
            if (this.SelectMode == PathSelectMode.GetDirectory && !String.IsNullOrEmpty(path))
            {
                p = path.Trim();
                if (p[p.Length - 1] != System.IO.Path.DirectorySeparatorChar)
                    p = p + System.IO.Path.DirectorySeparatorChar;
            }
            this.Txt.Text = p;
			this._SelectedPath = p;
		}
        #endregion
    }
    #region enum PathSelectMode : režim dialogu
    /// <summary>
    /// PathSelectMode : režim dialogu v panelu FileSelectPanel
    /// </summary>
    public enum PathSelectMode
	{
		/// <summary>Najít existující soubor pro načtení</summary>
		GetFile,
		/// <summary>Určit existující / neexistující soubor pro uložení</summary>
		PutFile,
        /// <summary>Určit adresář dialogem FolderBrowserDialog</summary>
		GetDirectory,
        /// <summary>Určit adresář výběrem některého souboru</summary>
        GetDirectoryFromFile
	}
    #endregion
}
